#!/usr/bin/env python

import os
import sys
import time
import datetime
import calendar
import socket
import xmlrpclib
from ConfigParser import RawConfigParser
import subprocess
import threading

import ttutils
from superdaemon import SuperDaemon

EXTHOST = ""
EXTPORT = 9999
LOCALPORT = 9998
PWDFILE = os.path.join(os.path.expanduser('~'), '.hyperiontv', 'tpvrpwd')
CONFFILE = os.path.join(os.path.expanduser('~'), '.hyperiontv', 'tpvrserver_conf')

class TpvrFuncs():
    conffile = CONFFILE
    transcode_queue = []
    nextShow = ()
   
    def __init__(self, log = None):
        self.user_info = {
            'uuid':''
        }
        self.command_info = {
            'pre_record':'CHAN=%%s',
            'record_device':'/dev/video0',
            'post_record':'VIDDIR=%%s; INFILE=%%s',
            'padding':'0',
            'video_dir':'.'
        }
        if log:
            self.log = log

    def setup(self):
        self.log.debug("Setup")
        self.getConf()
        self.log.debug("Got conf")
        if not self.user_info.get('uuid'):
            if self.log:
                self.log.critical("Missing UUID, please run tpvrconfig.")
            else:
                print "Missing UUID, please run tpvrconfig."
            sys.exit(1)

    def close(self):
        self.setConf()

    def setConf(self):
        conf = RawConfigParser()
        conf.add_section('User')
        for key in self.user_info:
            conf.set('User', key, str(self.user_info.get(key,'')))

        conf.add_section('Commands')
        for key in self.command_info:
            conf.set('Commands', key, str(self.command_info.get(key,'')))
        h = open(self.conffile, 'w')
        try:
            conf.write(h)
        finally:
            h.close()

    def getConf(self):
        if os.path.isfile(self.conffile):
            conf = RawConfigParser()
            conf.read(self.conffile)
            self.user_info = dict(conf.items('User'))
            self.command_info = dict(conf.items('Commands'))
        else:
            confdir = os.path.dirname(self.conffile)
            if not os.path.exists(confdir):
                os.makedirs(confdir)
            self.setConf()

    def postRecord(self):
        self.log.info('Init postRecord thread.')
        while not self.dostop:
            if self.transcode_queue:
                vid = self.transcode_queue.pop(0)
                self.log.debug('POST_RECORD: %s' % self.command_info.get('post_record'))
                postrec_cmd = self.command_info.get('post_record') % (
                    self.command_info.get('video_dir'),
                    "%s" % vid
                )
                self.log.info("POST_RECORD: %s" % postrec_cmd)
                if self.log:
                    self.log.info("POST_RECORD: %s" % postrec_cmd)
                ret = subprocess.call(postrec_cmd, shell=True)
                if self.log:
                    self.log.info("POST_RECORD returned %s" % ret)
            else:
                time.sleep(15)

    def startRecord(self, show):
        self.log.debug(self.command_info.get('pre_record'))
        prerec_cmd = self.command_info.get('pre_record') % (
            show.get('rf_channel')
        )
        if self.log:
            self.log.info("PRE_RECORD: %s" % prerec_cmd)
        ret = subprocess.call(prerec_cmd, shell=True)
        if self.log:
            self.log.info("PRE_RECORD returned %s" % ret)

        start_time = show.get('start_time').timetuple()
        file_name = "%s-%s-%s_%s_%s_%s%s" % (
            show.get('title').replace(' ', '_'),
            show.get('episode_title').replace(' ', '_'),
            start_time[0],
            start_time[1],
            start_time[2],
            start_time[3],
            start_time[4]
        )

        out_path = os.path.join(
            self.command_info.get('video_dir'),
            '%s.mpg' % file_name
        )

        out_path = out_path.replace('~', os.path.expanduser('~'))

        #if os.path.isfile(out_path):
        #    self.log.info("File %s already exists." % out_path)
        #    return 1

        rec_dev =  self.command_info.get('record_device')
        self.log.info("RECORDING FROM: %s to %s" % (rec_dev, out_path))

        end_utc = show.get('end_time')
        start_time = end_utc.utcnow()

        #Try append instead of write to see what happens.
        # .. this is probably a bad idea.
        h = open(out_path, 'a')
        try:
            p = subprocess.Popen(["cat", rec_dev], shell=False, stdout=h)
            self.log.debug("Recording...")
            while end_utc > (end_utc.utcnow() - datetime.timedelta(seconds=60)) \
            and not self.dostop:
            #while end_utc.utcnow() < (start_time + datetime.timedelta(seconds=120)) \
            #and not self.dostop:
                time.sleep(60)
            p.terminate()
        finally:
            h.close()
        self.log.info("Done recording.")
        self.transcode_queue.append(file_name)

    def checkSchedule(self):
        shows = None
        try:
            shows = ttutils.getSchedule(self.user_info.get('uuid'))
        except IOError, err:
            self.log.info("Failed to get schedule. ERR: %s" % err)

        #self.log.debug(shows)
        if len(shows) > 0:
            show = shows[0]
            start_utc = show.get('start_time')
            cur_utc = start_utc.utcnow()
            if start_utc < (cur_utc + datetime.timedelta(seconds=120)):
                self.log.info("Start recording: %s, %s" % (
                    show.get('title'),
                    show.get('episode_title')
                ))
                self.startRecord(show)
            elif self.nextShow != show:
                self.log.info("Next will record %s (%s) at: %s" % (
                    show.get('title'),
                    show.get('episode_title'),
                    time.ctime(calendar.timegm(start_utc.timetuple()))
                ))
                self.nextShow = show


class TpvrServer(SuperDaemon, TpvrFuncs):
    def __init__(self, *kwds, **args):
        SuperDaemon.__init__(self, 'tpvrserver', [], *kwds, **args)
        TpvrFuncs.__init__(self)
        self.log.info("==============================")
        self.log.info("Initializing TpvrServer Daemon")

    def work(self):
        self.checkSchedule()
        time.sleep(30) 

    def run(self):
        self.log.info("Running TpvrServer Daemon.")
        self.setup()
        self.log.debug("Done with setup.")
        transcode_thread = threading.Thread(target = self.postRecord)
        self.log.debug("About to start thread.")
        transcode_thread.start()
        self.log.debug("Thread started...")
        SuperDaemon.run(self)
        self.log.info("Stopping transcode thread.")
        transcode_thread.join(6)
        self.log.info("Thread stopped.")
        self.log.info("Done with run.")


if __name__ == "__main__":
    daemon = TpvrServer('/var/run/tpvr-server.pid')
    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            daemon.start()
        elif 'stop' == sys.argv[1]:
            try:
                xmlrpclib.ServerProxy("http://%s:%s" % ("localhost", LOCALPORT)).safeStop()
            except socket.error:
                print "Appears to already be stopped."
            daemon.stop()
        elif 'restart' == sys.argv[1]:
            print "Directing process to safely stop.."
            xmlrpclib.ServerProxy("http://%s:%s" % ("localhost", LOCALPORT)).safeStop()
            print "Restarting daemon.."
            daemon.restart()
            print "Done."
        elif 'forcestop' == sys.argv[1]:
            daemon.stop()
        else:
            print "Unknown command"
            sys.exit(2)
        sys.exit(0)
    else:
        print "usage: %s start|stop|restart|forcestop" % sys.argv[0]
        sys.exit(2)
